/*	--- 部署 --- 

对【一个Web应用程序】来说，除了【Servlet、Filter】这些【逻辑组件】，还需要【JSP】这样的【视图文件】，以及外加【一堆静态资源文件，如CSS、JS等】。

合理组织【文件结构】非常重要。

---------------------------------------

我们以【一个具体的Web应用程序】为例：

	webapp
	├── pom.xml
	└── src
	    └── main
	        ├── java
	        │   └── com
	        │       └── itranswarp
	        │           └── learnjava
	        │               ├── Main.java
	        │               ├── filter
	        │               │   └── EncodingFilter.java
	        │               └── servlet
	        │                   ├── FileServlet.java
	        │                   └── HelloServlet.java
	        ├── resources
	        └── webapp
	            ├── WEB-INF
	            │   └── web.xml
	            ├── favicon.ico
	            └── static         <-------------- 所有的静态资源文件
	                └── bootstrap.css


我们把【所有的静态资源文件】放入【/static/目录】

在开发阶段，有些【Web服务器】会自动为我们加一个【专门负责处理"静态文件" 的 Servlet】 ，但如果【IndexServlet】映射路径为"/"，会屏蔽掉【处理"静态文件" 的 Servlet映射】。

-----------------------------

因此，我们需要自己编写一个【处理"静态文件"的FileServlet】： */
@WebServlet(urlPatterns = "/static/*")
public class FileServlet extends HttpServlet {
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {

		ServletContext ctx = req.getServletContext();
		// RequestURI包含ContextPath, 需要去掉ContextPath
		String urlPath = req.getRequestURI().substring(ctx.getContextPath().length());
			// 外部路径 urlPath = req.getRequestURI() - req.getServletContext().getContextPath()
		String filepath = ctx.getRealPath(urlPath);
			// 内部路径 filepath = SrevletContext.getRealPath(urlPath);
			//通过 ServletContext将 urlPath -> filepath

		if (filepath == null) {
			// 无法获取到路径
			resp.sendError(HttpServletResponse.SC_NOT_FOUND);
			return ;
		}

		Path path = Paths.get(filepath); // Paths.get(内部路径);

		if (!path.toFile().isFile()) {
			// 无法获取到路径
			resp.sendError(HttpServletResponse.SC_NOT_FOUND);
			return ;
		}

		// 根据【文件名】猜测【Content-Type】
		String mime = Files.probeContentType(path);

		if (mime == null) {
			mime = "application/octet-stream";
		}
		resp.setContentType(mime);

		// 【读取文件】并【写入Response】
		OutputStream output = resp.getOutputStream();

		try (InputStream input = new BufferedInputStream(new FileInputStream(filepath))) { // 缓冲数据流 <- 文件输入流 <- 内部路径
			input.transferTo(output); // 输入流(内容) > 输出流
		}

		output.flush(); 
	}
}



/*
这样一来，在【开发阶段】，我们就可以【方便地高效开发】。

类似【Tomcat】这样的【Web服务器】，运行的【Web应用程序】通常都是【业务系统】

因此，【Tomcat这类服务器】也被称为【应用服务器】。

【应用服务器】并不擅长处理【静态文件】，也不适合直接暴露给用户。

通常，我们在【生产环境】部署时，总是使用【类似Nginx这样的服务器】充当【反向代理】和【静态服务器】，只有【动态请求】才会放行给【应用服务器】

所以，【部署架构】如下：

             ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐

             │  /static/*            │
┌───────┐      ┌──────────> file
│Browser├────┼─┤                     │    ┌ ─ ─ ─ ─ ─ ─ ┐
└───────┘      │/          proxy_pass
             │ └─────────────────────┼───>│  Web Server │
                       Nginx
             └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘    └ ─ ─ ─ ─ ─ ─ ┘




实现【上述功能】的【Nginx配置文件】如下： 
----------------------------------------------
server {
    listen 80;

    server_name www.local.liaoxuefeng.com

    # 静态文件根目录:
    root /path/to/src/main/webapp;

    access_log /var/log/nginx/webapp_access_log;
    error_log  /var/log/nginx/webapp_error_log;

    # 处理静态文件请求:
    location /static {
    }

    # 处理静态文件请求:
    location /favicon.ico {
    }

    # 不允许请求/WEB-INF:
    location /WEB-INF {
        return 404;
    }

    # 其他请求转发给Tomcat:
    location / {
        proxy_pass       http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
----------------------------------------------------

#	Nginx  代理服务器,负载均衡,反向代理,服务器架构

使用【Nginx】配合【Tomcat服务器】，可以充分发挥【Nginx】作为【网关】的优势，既可以高效处理静态文件，也可以把【https、防火墙、限速、反爬虫等功能】放到【Nginx】中，使得我们自己的【WebApp】能专注于【业务逻辑】。


===========================================================

#	练习

使用Nginx+Tomcat部署 */



/*========================================================

#	----- 部署 の 小结 ----- 


1. 部署【Web应用程序】时，要设计【合理的目录结构】，同时考虑【开发模式】需要【便捷性】，【生产模式】需要【高性能】。




*/












































